#if UNITY_EDITOR || UNITY_STANDALONE || UNITY_ANDROID || UNITY_IOS

using System;
using UnityEngine;

namespace uMicrophoneWebGL
{
    public class EditorMicrophoneDataRetriever : MonoBehaviour
    {
        public DataEvent dataEvent { get; } = new DataEvent();
        public bool playMicrophoneSound { get; set; } = false;

        private AudioClip _clip;
        private bool _isRecording = false;
        private string _deviceName = "";
        private int lastSamplePosition = 0;
        private int currentPosition = 0;
        private float[] _data = null;
        private int recordLengthSec = 3;
        private float[] _buffer = new float[256];
        
        // 缓存数组以减少GC
        private float[] _tempCopyBuffer = new float[256];
        
        // 避免在Update中创建委托
        private int _freq = 0;
        private int _dataLength = 0;

        public void Begin(string deviceName, int freq, int bufferSize = 256)
        {
            if (_isRecording) return;
            
            _freq = freq;
            _dataLength = recordLengthSec * freq;
            
            // 重新分配数组时检查大小
            if (_data == null || _data.Length != _dataLength)
            {
                _data = new float[_dataLength];
            }
            
            if (_buffer.Length != bufferSize)
            {
                _buffer = new float[bufferSize];
            }
            
            if (_tempCopyBuffer.Length != bufferSize)
            {
                _tempCopyBuffer = new float[bufferSize];
            }

            _deviceName = deviceName;
            _clip = Microphone.Start(_deviceName, true, recordLengthSec, freq);

            int retryCount = 0;
            while (Microphone.GetPosition(_deviceName) <= 0)
            {
                if (++retryCount >= 1000)
                {
                    Debug.LogError("Failed to get microphone.");
                    return;
                }
                System.Threading.Thread.Sleep(1);
            }
            lastSamplePosition = Microphone.GetPosition(_deviceName);
            _isRecording = true;
        }

        private float timer = 0f;
        private float interval = 0.02f;

        void Update()
        {
            if (!_isRecording)
            {
                return;
            }
            timer += Time.deltaTime;
            if (timer >= interval)
            {
                GetData();
                timer = 0;
            }
        }

        void GetData()
        {
            currentPosition = Microphone.GetPosition(_deviceName);
            if (currentPosition < 0 || lastSamplePosition == currentPosition)
            {
                return;
            }

            // 直接获取到_data数组，避免额外的数组操作
            _clip.GetData(_data, 0);

            // 内联函数以避免委托创建
            int GetDataLength(int head, int tail)
            {
                return head < tail ? tail - head : _dataLength - head + tail;
            }

            int bufferLength = _buffer.Length;
            int dataLength = GetDataLength(lastSamplePosition, currentPosition);

            while (dataLength > bufferLength)
            {
                var remain = _dataLength - lastSamplePosition;
                if (remain < bufferLength)
                {
                    // 分两段复制，使用临时缓冲区减少数组操作
                    Array.Copy(_data, lastSamplePosition, _tempCopyBuffer, 0, remain);
                    Array.Copy(_data, 0, _tempCopyBuffer, remain, bufferLength - remain);
                    
                    // 将临时缓冲区内容复制到目标缓冲区
                    Array.Copy(_tempCopyBuffer, 0, _buffer, 0, bufferLength);
                }
                else
                {
                    Array.Copy(_data, lastSamplePosition, _buffer, 0, bufferLength);
                }
                
                dataEvent.Invoke(_buffer);
                
                lastSamplePosition += bufferLength;
                if (lastSamplePosition >= _dataLength)
                {
                    lastSamplePosition -= _dataLength;
                }
                
                // 更新数据长度
                dataLength = GetDataLength(lastSamplePosition, currentPosition);
            }
        }

        public void End()
        {
            if (_isRecording)
            {
                Microphone.End(_deviceName);
                _isRecording = false;
            }
        }
    }
}

#endif